package oauth2

import (
    "errors"
    "github.com/astaxie/beego"
    "github.com/udoyu/utils/simini"
    "code.google.com/p/goprotobuf/proto"
    ."git.oschina.net/xyit/oauth2s/app"
)

type Oauth2Controller struct {
    beego.Controller
}

const (
    OAUTH2 = "oauth2"
)

func InitWeb(ini *simini.SimIni) int {
    rootPath := ini.GetStringVal(OAUTH2, "rootpath")
    length := len(rootPath)
    if length == 0 {
        rootPath = "/oauth2/"
    } else if rootPath[length-1] != '/' {
        rootPath += "/"
    }
    if rootPath[0] != '/' {
        rootPath = "/" + rootPath
    }
    beego.Router(rootPath + "web_apply", &Oauth2Controller{}, "post:WebApply")
    beego.Router(rootPath + "auth_code", &Oauth2Controller{}, "get:AuthCode")
    beego.Router(rootPath + "access_token", &Oauth2Controller{}, "get:AccessToken")
    beego.Router(rootPath + "get_token_info", &Oauth2Controller{}, "get:TokenInfo")
    return 0
}

func (this *Oauth2Controller) WebApply() {
    var err error
    req  := WebApplyReq{}
    resp := WebApplyResp{}

    v_uid := this.GetSession("uid")
    name := this.Ctx.Input.Query("name")
    url := this.Ctx.Input.Query("url")
    if v_uid==nil || len(name)==0 || len(url)==0 {
            err = errors.New("required paramer")
    } else {
        req.Uid = proto.Uint32(v_uid.(uint32))
        req.Name = proto.String(name)
        req.Url = proto.String(url)
        err = WebApply(&req, &resp)
    }
    if err != nil {
        error_info := &ErrorInfo{
            Error    :proto.String(err.Error()),
            ErrorCode:proto.Int32(1),
            Request  :proto.String(this.Ctx.Input.Url()),
        }
        this.Data["json"]=error_info
    } else {
        this.Data["json"]=resp
    }
    this.ServeJson()
}

func (this *Oauth2Controller) AuthCode() {
    var err error
    req  := AuthCodeReq{}
    resp := AuthCodeResp{}

    v_auth_uid := this.GetSession("auth_uid")
    client_id := this.Ctx.Input.Query("client_id")
    redirect_uri := this.Ctx.Input.Query("redirect_uri")
    state := this.Ctx.Input.Query("state")
    display := this.Ctx.Input.Query("display")
    scope := this.Ctx.Input.Query("scope")
    forcelogin_str := this.Ctx.Input.Query("forcelogin")
    if v_auth_uid==nil || forcelogin_str == "true" {
        //To do ... return the login web
        return
    } else if len(client_id)==0 || len(redirect_uri)==0 {
            err = errors.New("required paramer miss!")
    } else {
        req.Uid = proto.Uint32(v_auth_uid.(uint32))
        req.ClientId = proto.String(client_id)
        req.RedirectUri = proto.String(redirect_uri)
        req.State = proto.String(state)
        req.Display = proto.String(display)
        req.Scope = proto.String(scope)
        err = AuthCode(&req, &resp)
    }
    if err != nil {
        error_info := &ErrorInfo{
            Error    :proto.String(err.Error()),
            ErrorCode:proto.Int32(2),
            Request  :proto.String(this.Ctx.Input.Url()),
        }
        this.Data["json"]=error_info
        this.ServeJson()
    } else {
        redirect_uri = redirect_uri + "?code=" + *resp.Code
        this.Ctx.Redirect(301, redirect_uri)
    }
}

func (this *Oauth2Controller) AccessToken() {
    var err error
    req  := AccessTokenReq{}
    resp := AccessTokenResp{}

    client_id := this.Ctx.Input.Query("client_id")
    client_secret := this.Ctx.Input.Query("client_secret")
    grant_type := this.Ctx.Input.Query("grant_type")
    code := this.Ctx.Input.Query("code")
    if len(client_id)==0 || len(client_secret)==0 || 
       len(grant_type)==0 || len(code)==0 {
            err = errors.New("required paramer miss!")
    } else {
        req.ClientId = proto.String(client_id)
        req.ClientSecret = proto.String(client_secret)
        req.GrantType = proto.String(grant_type)
        req.Code = proto.String(code)
        err = AccessToken(&req, &resp)
    }
    if err != nil {
        error_info := &ErrorInfo{
                           Error    :proto.String(err.Error()),
                           ErrorCode:proto.Int32(2),
                           Request  :proto.String(this.Ctx.Input.Url()),
                       }
        this.Data["json"]=error_info
    } else {
        this.Data["json"]=resp
    }
    this.ServeJson()
}

func (this *Oauth2Controller) TokenInfo() {
    var err error
    req  := TokenInfoReq{}
    resp := TokenInfoResp{}

    access_token := this.Ctx.Input.Query("access_token")
    if len(access_token) == 0 {
        err = errors.New("required paramer miss!")
    } else {
        req.AccessToken = proto.String(access_token)
        err = TokenInfo(&req, &resp)
    }
    if err != nil {
        error_info := &ErrorInfo{
                           Error    :proto.String(err.Error()),
                           ErrorCode:proto.Int32(2),
                           Request  :proto.String(this.Ctx.Input.Url()),
                       }
        this.Data["json"]=error_info
    } else {
        this.Data["json"]=resp
    }
    this.ServeJson()
}
